#pragma once
/*!
 * \file 
 * AviParser.h
 */

#include <Vfw.h>

#define _TEST_STREAM_
#undef _TEST_STREAM_

/*!
 * \brief General information for an AVI files
 *
 * structure contains general information for an AVI files
 */
typedef struct _TAG_STREAM_INFO
{
	DWORD dwScale;	/**< Time scale applicable for the entire file. Dividing dwRate by dwScale gives the number of samples per second 	*/
	DWORD dwRate;	/**< Rate in an integer format. To obtain the rate in samples per second, divide this value by the value in dwScale 	*/
	DWORD dwEvent;	/**< a First DWORD-size value of the format of a user stream	*/
	ULONGLONG ullStart;		/**< Video Start time */
	ULONGLONG ullEnd;		/**< Video End time */
	ULONGLONG ullDuration;	/**< Elapsed time 	*/
	int nVideoLength;	/**< Total number of video samples 	*/
	int nVideoPos;	/**< This is used for internal purposes 	*/
	int nAudioLength;	/**< Total number of audio samples 	*/
	int nAudioPos;	/**< This is used for internal purposes 	*/
	DWORD dwAudioBufSize;	/**< Audio packet size per sample	*/
	DWORD dwAudioAvgBytes;	/**< Average audio data size per second 	*/			//per second

	BYTE *pUserFormat;		/**< Pointer to user format buffer 	*/
	DWORD dwUserFormatSize;	/**< Buffer size referenced by pUserFormat 	*/

	DWORD dwAudioVersion;	/**< Audio Stream Version 	*/

}ST_STREAM_INFO, *LPST_STREAM_INFO;

/*!
 * \brief Wrapping API associated with AVI file for parsing.
 *
 * This class is a wrapper of API functions associated with AVI file and stream
 * Especially focused on parsing AVI files
 *
 * - header file: AviParser.h
 * - lib: util.lib
 * - DLL: util.dll
 *
 */
class AFX_EXT_CLASS CAviParser
{
public:
	CAviParser(void);			/**< Contructor 	*/
	virtual ~CAviParser(void);	/**< Desturctor 	*/

private:
	PAVIFILE m_pAviFile;
	PAVISTREAM m_pAviStreamVideo;
	PAVISTREAM m_pAviStreamAudio;

	LONGLONG m_llTimeInfo;		//unit is millisec

	ST_STREAM_INFO m_stStreamInfo;
	BYTE *m_pVideoStream;
	BYTE *m_pAudioStream;
	BYTE *m_pUserStream;
	BYTE *m_pUserFormat;
	DWORD m_dwUserFormatSize;

	PAVISTREAM m_pAviStreamUser;


	DWORD m_dwUserDataSize;
	int m_nAVICount;
	WAVEFORMATEX m_WaveFormatEx;

	BYTE *m_pUserStreamAll;
	DWORD m_dwUserStreamSizeAll;
	DWORD m_dwUserStreamAlloc;
	DWORD m_dwDefaultUserDataSize;

	AVISTREAMINFO m_stAviStreamInfo;

#ifdef _TEST_STREAM_
	FILE *m_pFile;
#endif

	//////////////////////////////////////////////////////////////////////////
	BOOL CheckDiskDrive(CString strFileName);


public:
	/*!
	 * Before reading a AVI file, This function gets some information about the target AVI file.
	 * When reading a AVI file, it read with the option of OF_PARSE. 
	 * That means only possible to get AVI file information but not read the file.
	 *
	 * @param strFileName Null terminated string containing the name of the file to open.
	 * @param lpStreamInfo Pointer to the ST_STREAM_INFO structure used to return AVI file information.
	 * @param nStreamNumber Count of the video stream type. Identifies which occurrence of the specified video stream type to access
	 *
	 * @return if TRUE, it is done successfully. FALSE otherwise.
	 * 
	 * @see _TAG_STREAM_INFO
	 */
	BOOL GetStreamInfo(CString strFileName, LPST_STREAM_INFO lpStreamInfo, int nStreamNumber = 0);
	BOOL isOpen();		/**< Indicates whether AVI file is opened.	*/
	BOOL isVideoOpen(); /**< Indicates whether the video stream is opened. 	*/
	BOOL isAudioOpen();	/**< Indicates whether the audio stream is opened. 	*/

	/*!
	 * Open AVI file for reading
	 *
	 * @param strFileName Null terminated string containing the name of the file to open.
	 *
	 * @param nStreamNumber Count of the stream type. Identifies which occurrence of the specified stream type to access
	 *
	 * @return if TRUE, the AVI file is successfully opened.
	 */
	BOOL OpenStream(CString strFileName, int nStreamNumber = 0);

	/*!
	 * Open a video stream
	 *
	 * @param nStreamNumber Count of the stream type. Identifies which occurrence of the specified stream type to access
	 *
	 * @return if TRUE, the video stream is successfully opened.
	 */
	BOOL OpenVideoStream(int nStreamNumber = 0);
	/*!
	 * Open a audio stream
	 *
	 * @return if TRUE, the audio stream is successfully opened.
	 */
	BOOL OpenAudioStream();

	/*!
	 * Closes AVI file. All streams are also closed when they have been opened.
	 */
	void CloseStream();
	void CloseVideoStream();	/**< Close the video stream 	*/
	void CloseAudioStream();	/**< Close the audio stream 	*/

	/*!
	 * This function returns the position of a sample.
	 *
	 * @param nStartPos Starting video frame for the search.
	 * @param nDirection Find nearest sample. if positive value, searches forward. Otherwise, searches backward.
	 * @param bKey Find a nearest key frame
	 * @param llTime returns milliseconds converted a stream position from sample to.
	 *
	 * @return the position of the video frame found or -1 if the search is unsuccessful.
	 */
	int FindVideoStream(int nStartPos, int nDirection, BOOL bKey, LONGLONG *llTime);
	/*!
	 * returns the start position of the stream
	 */
	int GetVideoStartPos();
	/*!
	 * Move to video sample position.
	 *
	 * @param nPos a video sample count to move.
	 */
	void SetStreamPosVideo(int nPos);
	/*!
	 * Move to audio sample position.
	 *
	 * @param nPos a audio sample count to move.
	 */
	void SetStreamPosAudio(int nPos);
	/*!
	 * This function returns the audio sample position from the video sample position.
	 *
	 * @param nVideoPos Video sample to convert to audio sample.
	 *
	 * @return Audio sample number.
	 */
	int GetStreamPosVideoToAudio(int nVideoPos);

	/*!
	 * This function reads video data and returns Pointer to a BIMAPINFOHEADER structure and other information.
	 *
	 * @param pBmpInfoHeader Pointer to the BITMAPINFOHEADER structure used to video data format.
	 * @param llTime returns the converted time.
	 * @param bKeyFrame returns whether the current video data is a key frame or not.
	 * @param nPos returns the position of video frame
	 *
	 * If a key frame, it returns TRUE.
	 * return if TRUE, the operation is successful.
	 */
	BOOL GetVideoHeader(BITMAPINFOHEADER *pBmpInfoHeader, LONGLONG *llTime, BOOL *bKeyFrame, int *nPos = NULL);
	/*!
	 * Get video data which is read at calling the function GetVideoHeader.
	 *
	 * @param dwSize size of video data.
	 *
	 * @return Pointer to the buffer contained video data.
	 */
	BYTE *GetVideoStream(DWORD dwSize);

	/*!
	 * This function reads audio data and returns pointer to a WAVEFORMATEX structure and other information.
	 *
	 * @param pWfx Pointer to the WAVEFORMATEX structure used to audio data format
	 * @param llTime returns the converted time.
	 * @param dwSize returns the size of an audio data
	 *
	 * @return if TRUE, the operation is successful.
	 */
	BOOL GetAudioHeader(WAVEFORMATEX *pWfx, LONGLONG *llTime, DWORD *dwSize);
	BYTE *GetAudioStream(DWORD dwSize);

	//////////////////////////////////////////////////////////////////////////
	//
	BOOL isUserOpen();	/**< Indicates whether the user stream is opened. 	*/
	/*!
	 * Open a user stream
	 *
	 * @return if TRUE, the user stream is successfully opened.
	 */
	BOOL OpenUserStream();
	void CloseUserStream();	/**< Close the user stream 	*/
	/*!
	 * When you read user data in advance, first of all you call this function.
	 * And then this object allocates buffers for containing the whole user data
	 */
	void ReadUserStreamInAdvance();

	/*!
	 * Get the format of a user stream
	 *
	 * @param dwSize Returns the size of user format
	 *
	 * @return Pointer to the buffer containing user format
	 */
	BYTE *GetUserFormat(DWORD *dwSize);
	BYTE *GetUserData();
	/*!
	 * Get the current user data of a user stream
	 *
	 * @param dwSize Returns the size of user data
	 * 
	 * @return Returns Pointer to the buffer containing user data
	 */
	BYTE *GetUserData(DWORD *dwSize);
	/*!
	 * Read the user data of a user stream referenced by position
	 *
	 * @param nPos Position
	 * @param dwSize Pointer to the value which contains size of user data.
	 *
	 * @return Returns pointer to the buffer which contains user data.
	 */
	BYTE *ReadUserData(int nPos, DWORD *dwSize);

	/*!
	 * Returns a total number of video samples.
	 *
	 * @return Total number of video samples.
	 */
	int GetVideoLength();

	int GetAudioFormat();		/**< Returns waveform-audio format type	*/
	int GetAudioFrequency();	/**< Returns audio frequency in Hz 	*/
	int GetAudioBitPerSample();	/**< Returns audio bit per sample 	*/

	DWORD GetTotalUserDataCount();		/**< Returns a total number of user data 	*/
	/**
	 * Returns a number of user data with the condition.
	 *
	 * @param llElapse Condition. 
	 *
	 * @return a number of user data counted from start position to the condition representative of llElapse
	 */
	DWORD GetTotalUserDataCount(LONGLONG llElapse);
	DWORD GetUserDataSizeAll();	/**< Returns a total bytes of user data 	*/
	BYTE *GetUserDataAll();	/**< Returns pointer to the user data which contains the whole data 	*/
	int GetCurrentUserDataPos(); /**<  Returns a current position of user data read	*/
	void SetDefaultUserDataSize(DWORD dwDefaultSize);

};
